#include <stdio.h>
#include <sqlite3.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include "debug.h"
#include "db_sqlite3.h"

static int integrity_check_cb(void *args, int argc, char **argv, char **azCols);

static int integrity_check(sqlite3 *db, int *corrupt);

static int file_exist(const char *filename, int *exist);

static int libinit(void);

/*****************************************************************************
 函 数 名  : integrity_check_cb
 功能描述  : 数据库完整性检查回调函数
 输入参数  :   int argc
           char **argv
           char**azCols

 输出参数  : void* userargs
                        DB_INTEGRITY_OK:数据库完整
                        DB_INTEGRITY_ERROR:数据库损坏
                        DB_INTEGRITY_UNKNOW:未知状态，回调函数出问题

 返 回 值  : static int
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
static int integrity_check_cb(void *userargs, int argc, char **argv, char **azCols)
{
    if (userargs == NULL)
    {
        return DB_ERROR_INVALID;
    }

    if (argc > 0 && (0 == strncmp(argv[0], "ok", 2)))
    {
        *((int *) userargs) = DB_INTEGRITY_OK;
    }
    else if (argc > 0 && (0 != strncmp(argv[0], "ok", 2)))
    {
        *((int *) userargs) = DB_INTEGRITY_ERROR;
    }
    else
    {
        *((int *) userargs) = DB_INTEGRITY_UNKNOW;
    }

    return SQLITE_OK;
}

/*****************************************************************************
 函 数 名  : integrity_check
 功能描述  : 检查数据库db的完整性，状态由corrupt保存
 输入参数  : sqlite3* db
 输出参数  : int *corrupt
                        DB_INTEGRITY_OK:数据库完整
                        DB_INTEGRITY_ERROR:数据库损坏
                        DB_INTEGRITY_UNKNOW:未知状态，回调函数出问题

 返 回 值  : static int
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
static int integrity_check(sqlite3 *db, int *corrupt)
{
    int rc;
    char *zErrMsg = 0;
    char *sql = "PRAGMA INTEGRITY_CHECK";

    if (db == NULL || corrupt == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, integrity_check_cb, corrupt, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return rc;
    }

    return SQLITE_OK;
}

/*****************************************************************************
 函 数 名  : file_exist
 功能描述  : 检查文件filename是否存在
 输入参数  : const char* filename
 输出参数: int *exist
                    0：不存在
                    1：存在
 输出参数  : 无
 返 回 值  : static int
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
static int file_exist(const char *filename, int *exist)
{
    int rc;

    if (filename == NULL || exist == NULL)
    {
        return DB_ERROR_INVALID;
    }

    rc = access(filename, F_OK);

    if (rc == -1)
    {
        if (errno == ENOENT)
        {
            *exist = 0;
        }
        else
        {
            return DB_ERROR_SYSCALL;
        }
    }
    else
    {
        *exist = 1;
    }

    return SQLITE_OK;
}

/*****************************************************************************
 函 数 名  : libinit
 功能描述  : 对sqlite库初始化，本封装仅支持多线程的串行模式
 输入参数  : void
 输出参数  : 无
 返 回 值  : int
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
static int libinit(void)
{
    int ret;

    ret = sqlite3_shutdown();
    if (ret != SQLITE_OK)
    {
        LOGE("SQL error:sqlite3_shutdown,errorcode:%d", ret);
    }

    if (0 == sqlite3_threadsafe())
    {
        LOGE("SQL error:Set thread safe");
        return DB_ERROR_UNSAFE;
    }

    ret = sqlite3_config(SQLITE_CONFIG_SERIALIZED);
    if (ret != SQLITE_OK)
    {
        LOGE("SQL error:Config,errorcode:%d", ret);
    }

    return ret;
}

/*****************************************************************************
 函 数 名  : sqldb_open
 功能描述  : 多线程串行方式打开数据库
 输入参数  : const char * filename
           const char*bakfile
 输出参数: sqlite3** pmemdb

 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_open(const char *filename, const char *bakfile, sqlite3 **pmemdb)
{
    int rc;

    if (filename == NULL || bakfile == NULL || pmemdb == NULL)
    {
        LOGE("parameters invalid");
        return DB_ERROR_INVALID;
    }

    rc = libinit();

    if (rc != SQLITE_OK)
    {
        LOGE("libinit error");
        return DB_ERROR_LIBINIT;
    }

    //打开内存数据库文件
    rc = sqlite3_open(":memory:", pmemdb);

    if (rc != SQLITE_OK)
    {
        LOGE("Can't open database: %s\n", sqlite3_errmsg(*pmemdb));
        return rc;
    }
    else
    {
        LOGI("Opened database successfully\n");
    }

    //从文件系统读入
    rc = sqldb_load(*pmemdb, filename, bakfile);

    if (rc != SQLITE_OK)
    {
        LOGE("Can't open database: %s\n", sqlite3_errmsg(*pmemdb));
        return rc;
    }

    return rc;
}

/*****************************************************************************
 函 数 名  : sqldb_close
 功能描述  : 关闭数据库db连接
 输入参数  : sqlite3* db
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_close(sqlite3 *db)
{
    if (db == NULL)
    {
        LOGE("parameters error");
        return DB_ERROR_INVALID;
    }

    return sqlite3_close_v2(db);
}

/*****************************************************************************
 函 数 名  : sqldb_recover
 功能描述  : 从数据库文件bakfile恢复数据库到db
 输入参数  : sqlite3* db
             const char* bakfile
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_recover(sqlite3 *db, const char *bakfile)
{
    int rc;
    int corrupt;
    sqlite3 *pBakFile;
    sqlite3_backup *pBackup;

    if (db == NULL || bakfile == NULL)
    {
        return DB_ERROR_INVALID;
    }

    rc = sqlite3_open(bakfile, &pBakFile);

    if (rc == SQLITE_OK)
    {
        rc = integrity_check(pBakFile, &corrupt);

        if (rc != SQLITE_OK)
        {
            LOGE("1 integrity_check failed\n");
            sqlite3_close(pBakFile);
            return rc;
        }

        //数据库损坏
        if (corrupt == DB_INTEGRITY_ERROR)
        {
            sqlite3_close(pBakFile);
            return DB_INTEGRITY_ERROR;
        }

        pBackup = sqlite3_backup_init(db, "main", pBakFile, "main");

        if (pBackup)
        {
            //备份时发生崩溃或者程序退出或者断电，将产生journal文件
            sqlite3_busy_timeout(db, 1000);
            do
            {
                rc = sqlite3_backup_step(pBackup, -1);
                if (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED)
                {
                    LOGE("backup timeout");
                    break;
                }
            } while (rc == SQLITE_OK || rc == SQLITE_LOCKED);

            sqlite3_backup_finish(pBackup);
        }

        rc = sqlite3_errcode(db);
    }

    (void) sqlite3_close(pBakFile);
    return rc;
}

/*****************************************************************************
 函 数 名  : sqldb_load
 功能描述  : 将数据库从磁盘文件dbfile加载至连接memdb，如果dbfile损坏，则从备份文件
           bakfile中加载。通常memdb是一个内存数据库。
 输入参数  : sqlite3* memdb
             const char* dbfile
             const char*bakfile
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

 特别注意:
   1.当日志文件产生了，使用一些sqlite可视化工具查看dbfile，会导致dbfile数据清空。
   此时再运行程序，会把清空后的数据备份至bakfile，会导致数据丢失。
*****************************************************************************/
int sqldb_load(sqlite3 *memdb, const char *dbfile, const char *bakfile)
{
    int rc;
    int corrupt;
    sqlite3 *pFile;
    sqlite3_backup *pBackup;
    char journal[64];
    int exists = 0, bakexists = 0, journalexists = 0;

    if (memdb == NULL || dbfile == NULL || bakfile == NULL)
    {
        return DB_ERROR_INVALID;
    }

    //判定日志文件是否存在，日志文件存在，会导致数据库文件清空
    snprintf(journal, 63, "%s-journal", dbfile);

    if (SQLITE_OK == file_exist(journal, &journalexists))
    {
        if (1 == journalexists)
        {
            unlink(dbfile);
            unlink(journal);
            corrupt = DB_INTEGRITY_ERROR;
        }
    }

    //判断文件是否存在？
    rc = file_exist(dbfile, &exists);

    if (rc != SQLITE_OK)
    {
        return rc;
    }

    //不存在则创建
    if (!exists)
    {
        rc = sqlite3_open_v2(dbfile, &pFile, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
    }
    else
    {
        rc = sqlite3_open_v2(dbfile, &pFile, SQLITE_OPEN_READWRITE, NULL);
    }

    if (rc == SQLITE_OK)
    {
        if (!exists)
        {
            //判断备份数据库文件是否存在？
            rc = file_exist(bakfile, &bakexists);

            if (rc != SQLITE_OK)
            {
                sqlite3_close_v2(pFile);
                return rc;
            }

            //备份数据库文件存在，尝试从备份数据库中恢复
            if (bakexists)
            {
                rc = sqldb_recover(pFile, bakfile);

                if (rc != SQLITE_OK)
                {
                    sqlite3_close_v2(pFile);
                    return rc;
                }
            }
        }
        else
        {
            rc = integrity_check(pFile, &corrupt);

            if (rc != SQLITE_OK)
            {
                LOGE("3 integrity_check failed\n");
                sqlite3_close_v2(pFile);
                return rc;
            }

            //数据库损坏，从备份中恢复
            if (corrupt == DB_INTEGRITY_ERROR)
            {
                rc = sqldb_recover(pFile, bakfile);

                if (rc != SQLITE_OK)
                {
                    sqlite3_close_v2(pFile);
                    return rc;
                }
            }
        }

        //加载至内存数据库
        pBackup = sqlite3_backup_init(memdb, "main", pFile, "main");

        if (pBackup)
        {
            //备份时发生崩溃或者程序退出或者断电，将产生journal文件
            sqlite3_busy_timeout(memdb, 1000);
            do
            {
                rc = sqlite3_backup_step(pBackup, -1);
                if (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED)
                {
                    LOGE("backup timeout");
                    break;
                }
            } while (rc == SQLITE_OK || rc == SQLITE_LOCKED);

            sqlite3_backup_finish(pBackup);
        }

        rc = sqlite3_errcode(memdb);
    }

    sqlite3_close_v2(pFile);
    return rc;
}

/*****************************************************************************
 函 数 名  : sqldb_save
 功能描述  : 将数据库db保存至文件dbfile，并且在存储前将dbfile备份至bakfile。
 输入参数  : sqlite3* db
             const char* zFilename
             const char* bakfile
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_save(sqlite3 *db, const char *dbfile, const char *bakfile)
{
    int rc;
    int corrupt;
    sqlite3 *pFile;
    sqlite3_backup *pBackup;

    if (db == NULL || dbfile == NULL || bakfile == NULL)
    {
        LOGE("parameters error");
        return DB_ERROR_INVALID;
    }

    //以最短的时间进行备份
    unlink(bakfile);
    rename(dbfile, bakfile);
    rc = sqlite3_open(dbfile, &pFile);

    if (rc == SQLITE_OK)
    {
        rc = integrity_check(db, &corrupt);

        if (rc != SQLITE_OK)
        {
            LOGE("4 integrity_check failed\n");
            //sqlite3_close(db);
            sqlite3_close(pFile);
            return rc;
        }

        if (corrupt == DB_INTEGRITY_OK)
        {
            pBackup = sqlite3_backup_init(pFile, "main", db, "main");

            if (pBackup)
            {
                //备份时发生崩溃或者程序退出或者断电，将产生journal文件
                sqlite3_busy_timeout(db, 1000);
                do
                {
                    rc = sqlite3_backup_step(pBackup, -1);
                    if (rc == SQLITE_BUSY || rc == SQLITE_IOERR_BLOCKED)
                    {
                        LOGE("backup timeout");
                        break;
                    }
                } while (rc == SQLITE_OK || rc == SQLITE_LOCKED);

                sqlite3_backup_finish(pBackup);
            }

            rc = sqlite3_errcode(pFile);
        }
    }

    sqlite3_close(pFile);
    return rc;
}

/*****************************************************************************
 函 数 名  : sqldb_slim
 功能描述  : 消除数据库db中所有或者指定表tablename的空闲页，使数据库变小。数据库
           在经过一些插入删除操作后，会出现空闲页，占用数据库存储空间。
 输入参数  : sqlite3* db            
             const char* tablename  
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_slim(sqlite3 *db, const char *tablename)
{
    char *zErrMsg = 0;
    int rc;
    char sql[128];

    if (db == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Create SQL statement */
    if (tablename == NULL)
    {
        snprintf(sql, 8, "VACUUM;");
    }
    else
    {
        snprintf(sql, 127, "VACUUM %s;", tablename);
    }
    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, NULL, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return rc;
    }

    return SQLITE_OK;
}

/*****************************************************************************
 函 数 名  : sqldb_transaction_begin
 功能描述  : 开启事务
 输入参数  : sqlite3* db
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_transaction_begin(sqlite3 *db)
{
    int rc;
    char *zErrMsg = 0;

    if (db == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Execute SQL statement */
    rc = sqlite3_exec(db, "BEGIN;", NULL, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    else
    {
        LOGI("Operation done successfully\n");
    }

    return rc;
}

/*****************************************************************************
 函 数 名  : sqldb_transaction_commit
 功能描述  : 提交事务
 输入参数  : sqlite3* db
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_transaction_commit(sqlite3 *db)
{
    int rc;
    char *zErrMsg = 0;

    if (db == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Execute SQL statement */
    rc = sqlite3_exec(db, "COMMIT;", NULL, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }
    else
    {
        LOGI("Operation done successfully\n");
    }

    return rc;
}

/*****************************************************************************
 函 数 名  : sqldb_exec_restrain_batch
 功能描述  : 测试批量操作
 输入参数  : sqlite3* db
             const char* sql
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_exec_restrain_batch(sqlite3 *db, const char *sql)
{
    int i = 0;
    int rc;
    const char *sqltail;
    sqlite3_stmt *stmt;

    if (db == NULL || sql == NULL)
    {
        return DB_ERROR_INVALID;
    }

    rc = sqlite3_prepare_v2(db, sql, -1, &stmt, &sqltail);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", sqlite3_errmsg(db));
    }

    while (i++ < 100)
    {
        sqlite3_reset(stmt);
        sqlite3_bind_int(stmt, 1, i);
        sqlite3_bind_text(stmt, 2, "thomas", -1, SQLITE_STATIC);
        sqlite3_bind_int(stmt, 3, 29);
        sqlite3_bind_text(stmt, 4, "shenzhen", -1, SQLITE_STATIC);
        sqlite3_bind_int(stmt, 5, 50000);
        rc = sqlite3_step(stmt);
    }

    return sqlite3_finalize(stmt);
}

/*****************************************************************************
 函 数 名  : sqldb_create_table
 功能描述  : 如果表tablename不存在，则创建，声明语句为declarelist
 输入参数  : sqlite3* db
             const char* tablename
             const char* declarelist
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_create_table(sqlite3 *db, const char *tablename, const char *declarelist)
{
    char *zErrMsg = 0;
    int rc;
    char sql[2048];

    if (db == NULL || tablename == NULL || declarelist == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Create SQL statement */
    snprintf(sql, 2047, "CREATE TABLE IF NOT EXISTS %s (%s);", tablename, declarelist);
    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, NULL, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return rc;
    }
    else
    {
        LOGI("Table created successfully\n");
    }

    return rc;
}

/*****************************************************************************
 函 数 名  : sqldb_drop_table
 功能描述  : 删除表
 输入参数  : sqlite3* db            
             const char* tablename  
 输出参数  : 无
 返 回 值  : 
 调用函数  : 
 被调函数  : 
 
 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_drop_table(sqlite3 *db, const char *tablename)
{
    char *zErrMsg = 0;
    int rc;
    char sql[64];

    if (db == NULL || tablename == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Create SQL statement */
    snprintf(sql, 63, "DROP TABLE %s;", tablename);
    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, NULL, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return rc;
    }
    else
    {
        LOGI("Table drop successfully\n");
    }

    return rc;
}

/*****************************************************************************
 函 数 名  : sqldb_insert
 功能描述  : 数据插入
 输入参数  : sqlite3* db
             const char* tablename:表名
             const char* columnlist:列名列表
             const char *valuelist:列值列表
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_insert(sqlite3 *db, const char *tablename, const char *columnlist, const char *valuelist)
{
    char *zErrMsg = 0;
    int rc;
    char sql[512];

    if (db == NULL || tablename == NULL || columnlist == NULL || valuelist == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Create SQL statement */
    snprintf(sql, 511, "INSERT INTO %s (%s) VALUES (%s)", tablename, columnlist, valuelist);
    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, NULL, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return rc;
    }

    return SQLITE_OK;
}

/*****************************************************************************
 函 数 名  : sqldb_replace
 功能描述  : 数据不存在则插入，存在则更新，数据必须有由UNIQUE修饰的列，否则会重复插入
 输入参数  : sqlite3* db
             const char* tablename:表名
             const char* columnlist:列名列表
             const char *valuelist:列值列表
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月23日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_replace(sqlite3 *db, const char *tablename, const char *columnlist, const char *valuelist)
{
    char *zErrMsg = 0;
    int rc;
    char sql[512];

    if (db == NULL || tablename == NULL || columnlist == NULL || valuelist == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Create SQL statement */
    snprintf(sql, 511, "REPLACE INTO %s (%s) VALUES (%s)", tablename, columnlist, valuelist);
    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, NULL, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return rc;
    }

    return SQLITE_OK;
}

/*****************************************************************************
 函 数 名  : sqldb_select
 功能描述  : 数据查询
 输入参数  : sqlite3* db
             const char *columnlist:列名列表
             const char* tablename:表名
             const char* conditions:可选条件
             sqliteSelectcallback callback:查询结果回调函数
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_select(sqlite3 *db, const char *columnlist, const char *tablename, const char *conditions,
                 sqliteSelectcallback callback, void *args)
{
    int rc;
    char *zErrMsg;
    char sql[512];
    char **azResult;
    int nRow;
    int nColumn;

    if (db == NULL || tablename == NULL || columnlist == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Create SQL statement */
    if (conditions != NULL)
    {
        snprintf(sql, 511, "SELECT %s FROM %s WHERE %s;", columnlist, tablename, conditions);
    }
    else
    {
        snprintf(sql, 511, "SELECT %s FROM %s;", columnlist, tablename);
    }

    rc = sqlite3_get_table(db, sql, &azResult, &nRow, &nColumn, &zErrMsg);
    if (rc != SQLITE_OK)
    {
        LOGE("db select error:%s", zErrMsg);
        return rc;
    }

    callback(nRow, nColumn, azResult, args);

    sqlite3_free_table(azResult);
    return SQLITE_OK;
}

/*****************************************************************************
 函 数 名  : sqldb_update
 功能描述  : 数据修改
 输入参数  : sqlite3* db
             const char* tablename :表名
             const char* expressions：赋值表达式
             const char* conditions ：可选条件
             sqliteExecallback callback  :回调函数
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_update(sqlite3 *db, const char *tablename, const char *expressions, const char *conditions,
                 sqliteExecallback callback)
{
    char *zErrMsg = 0;
    int rc;
    char sql[512];

    if (db == NULL || tablename == NULL || expressions == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Create merged SQL statement */
    if (conditions != NULL)
    {
        snprintf(sql, 511, "UPDATE %s SET %s WHERE %s;", tablename, expressions, conditions);
    }
    else
    {
        snprintf(sql, 511, "UPDATE %s SET %s;", tablename, expressions);
    }

    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, callback, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
        return rc;
    }

    return SQLITE_OK;
}

/*****************************************************************************
 函 数 名  : sqldb_delete
 功能描述  : 数据删除
 输入参数  : sqlite3* db
             const char* tablename :表名
             const char* conditions:删除条件
             sqliteExecallback callback:回调函数
 输出参数  : 无
 返 回 值  :
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2020年6月11日
    作    者   : thomas
    修改内容   : 新生成函数

*****************************************************************************/
int sqldb_delete(sqlite3 *db, const char *tablename, const char *conditions, sqliteExecallback callback)
{
    char *zErrMsg = 0;
    int rc;
    char sql[512];

    if (db == NULL || tablename == NULL || conditions == NULL)
    {
        return DB_ERROR_INVALID;
    }

    /* Create merged SQL statement */
    snprintf(sql, 511, "DELETE FROM %s WHERE %s;", tablename, conditions);
    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, callback, NULL, &zErrMsg);

    if (rc != SQLITE_OK)
    {
        LOGE("SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }

    return rc;
}
